ARD2  RC2
Airbag Reference Demonstrator using MPC5604P
CG147.c
Go to the documentation of this file.
00001 
00020 #include "Compile_Options.h"
00021 #include "derivative.h"
00022 #include "ADC.h"
00023 #include "CG147.h"
00024 #include "eDMA.h"  /* To Have periodic watchdog transfers */
00025 #include "PIT.h"   /* Same as above */
00026 #include "DSPI.h"  /* To send and receive */
00027 #include "CGM.h"   /* To configure 2MHz clock output through CLKOUT */
00028 #include "MailScheduler.h"
00029 #include "HAL.h"   /* To use delay macros */
00030 #include "SIU.h"   /* To toggle pins */ 
00031 #include "UTILS.h"
00032 #include <limits.h>
00033 /*
00034  ******************************************************************************
00035  * Constants
00036  ******************************************************************************
00037  */
00038 const CGMCLKOutConfig_t ctCG147ClkOutConfig =
00039 {
00040   (CLK_OUT_ENABLE | CLK_OUT_DIV_BY_8 | CLK_OUT_SOURCE_PLL1) };
00041 /* Next two constants are used to read all PSI5 sensors in order             */
00042 /* First command selects channel 0 for the next command.                     */
00043 /* The next commands are always acceleration requests, and arguments select  */
00044 /* the channel for then upcoming request.                                    */
00045 const uint8_t cau8ReadPSISensorsCmd[] =
00046 {
00047   SBC_SELECT_PSI, SBC_READ_PSI, SBC_READ_PSI, SBC_READ_PSI, SBC_READ_PSI,
00048   SBC_READ_PSI, SBC_READ_PSI, SBC_READ_PSI, SBC_READ_PSI, SBC_READ_PSI,
00049   SBC_READ_PSI, SBC_READ_PSI, SBC_READ_PSI };
00050 const uint8_t cau8ReadPSISensorsArg[] =
00051     {
00052       0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0C, 0x0D, 0x0E,
00053       0x00 };
00054 /* Next two commands shall be used in 16-bit mode to configure the device */
00055 /* and switch to 17-bit mode.                                             */
00056 const uint8_t cau8CG147InitCmdsIn16Bit[] = 
00057 {
00058   SBC_POWER_CTRL,  /* Remove EMC noise coming from DC-DC converter */
00059   SBC_ENABLE_PROG, /* Allow the following operations to take place */
00060   SBC_PROG_POWER,  /* Program power */
00061   SBC_PROG_PSI1_LINE, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */
00062   SBC_PROG_PSI2_LINE, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */
00063   SBC_PROG_PSI3_LINE, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */
00064   SBC_PROG_PSI4_LINE, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */
00065   SBC_PROG_PSYNC_MODE, /* Detect reg off, i reg on, time slot on, manual psync, 2usec between ch */
00066   SBC_PSI_SUPPLY,      /* All four power supplies on */
00067   SBC_PSI_SYNC_MASK,   /* All four PSI5 channels on */
00068   SBC_PROG_PSI_SID,    /* SBC_PROG_PSI_SID => otherwise default SID=111 */
00069   SBC_PROG_PSI_SID,    /* SBC_PROG_PSI_SID => otherwise default SID=111 */
00070   SBC_PROG_PSI_SID,    /* SBC_PROG_PSI_SID => otherwise default SID=111 */
00071   SBC_PROG_PSI_SID,    /* SBC_PROG_PSI_SID => otherwise default SID=111 */
00072   SBC_PROG_UFS_THRES,  /* Thresholds */
00073   SBC_PROG_PAS_THRES,  /* Thresholds */
00074   SBC_PROG_PRES_THRES, /* Thresholds */
00075   SBC_PROG_ROLL_THRES, /* Thresholds */
00076   SBC_PROG_X_THRES,    /* Thresholds */
00077   SBC_PROG_Y_THRES,    /* Thresholds */
00078   SBC_PROG_FLM_CONF,   /* This configures firing time and current */
00079   SBC_PROG_ENH_SAFETY  /* SPI Data will necessarily be 17-bit transfers after this */
00080   /* Note that EOP is missing - it must be sent as a 17-bit word now */
00081 };
00082 const uint8_t cau8CG147InitArgsIn16Bit[] = 
00083 {
00084   CG147_DEFAULT_POWER_STG,  /* Remove EMC noise coming from DC-DC converter */
00085   0x02u, /* Allow the following operations to take place */
00086   0x00u,  /* Program power */
00087   0x40u, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */
00088   0x40u, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */
00089   0x40u, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */
00090   0x40u, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */
00091   0xC1u, /* Detect reg off, i reg on, time slot on, manual psync, 2usec between ch */
00092   0xCFu,      /* All four power supplies on */
00093   0x0Fu,   /* All four PSI5 channels on */
00094   0x00u,    /* SBC_PROG_PSI_SID => otherwise default SID=111 */
00095   0x20u,    /* SBC_PROG_PSI_SID => otherwise default SID=111 */
00096   0x40u,    /* SBC_PROG_PSI_SID => otherwise default SID=111 */
00097   0x60u,    /* SBC_PROG_PSI_SID => otherwise default SID=111 */
00098   0x05u,  /* Thresholds */
00099   0x05u,  /* Thresholds */
00100   0x00u, /* Thresholds */
00101   0x00u, /* Thresholds */
00102   0x00u,    /* Thresholds */
00103   0x00u,    /* Thresholds */
00104   0x00u,   /* This configures firing time and current */
00105   0x0Cu  /* SPI Data will necessarily be 17-bit transfers after this */
00106   /* Note that EOP is missing - it must be sent as a 17-bit word now */
00107 };
00108 /* Next value is used to determine size of previous two elements */
00109 const uint8_t cu8CG147InitCmdsArgsSize = N_ELEMENTS(cau8CG147InitCmdsIn16Bit);
00110 /* Following three tables are used when addressing both high side and low */
00111 /* side squibs, and by default turning them off.                          */
00112 static const uint8_t cau8CG147FireLSSquibsCmds[] =
00113 {
00114   SBC_LS_ON1_4, SBC_LS_ON5_8, SBC_LS_ON9_12 };
00115 static const uint8_t cau8CG147FireHSSquibsCmds[] =
00116 {
00117   SBC_HS_ON1_4, SBC_HS_ON5_8, SBC_HS_ON9_12, };
00118 static const uint8_t cau8CG147FireSquibsDfltArgs[] =
00119 {
00120   0xAA, /* HS_ON1_4: By default, all off. User should edit before sending */
00121   0xAA, /* HS_ON5_8: By default, all off. User should edit before sending */
00122   0xAA, /* HS_ON9_12 By default, all off. User should edit before sending */
00123 };
00124 /* Following tables are used when performing tests */
00125 static const uint8_t cau8CG147TestCmds[] =
00126 {
00127   SBC_POWER_CTRL, /* First instruction is to disable T2 */
00128   SBC_POWER_CTRL, /* Second instruction will be overwritten with a test */
00129   SBC_POWER_STATUS, /* Third will get the condition back */
00130   SBC_POWER_CTRL, /* Fourth will re-establish original settings */
00131 };
00132 static const uint8_t cau8CG147TestArgs[] =
00133 {
00134   /* With the T_EN bit within the SPI instruction POWER_CTRL being set */
00135   /* the transistor T2 of the boost converter is switched off.         */
00136   0x01u,
00137   /* Second argument is the test itself and should be overwritten by   */
00138   /* the actual command. Here set to FF as a place-holder.             */
00139   0xFFu,
00140   /* Verify the actual result */
00141   0x00u,
00142   /* Re-establish default settings */
00143   CG147_DEFAULT_POWER_STG };
00144 
00145 /* Next two constants serve as a list of Watch-dog responses.                */
00146 const uint8_t cau8CG147WDResponsesFromMCU[] =
00147 {
00148   SBC_WD_RESPONSE_8, SBC_WD_RESPONSE_1, SBC_WD_RESPONSE_2, SBC_WD_RESPONSE_3,
00149   SBC_WD_RESPONSE_4, SBC_WD_RESPONSE_5, SBC_WD_RESPONSE_6, SBC_WD_RESPONSE_7 };
00150 const uint8_t cau8CG147WDRequestsToMCU[] =
00151 {
00152   SBC_WD_CHECKWORD_1, SBC_WD_CHECKWORD_2, SBC_WD_CHECKWORD_3,
00153   SBC_WD_CHECKWORD_4, SBC_WD_CHECKWORD_5, SBC_WD_CHECKWORD_6,
00154   SBC_WD_CHECKWORD_7, SBC_WD_CHECKWORD_8 };
00155 
00156 /* Following table is a pre-calculation of all possible combinations */
00157 /* for a squib register being either on or off. It is used in combi- */
00158 /* nation with a mask to be sent as an argument to the CG147 device. */
00159 const uint8_t cau8SquibOnPrecalc[] =
00160 {
00161   0xAA, 0xA9, 0xA6, 0xA5, 0x9A, 0x99, 0x96, 0x95, 0x6A, 0x69, 0x66, 0x65, 0x5A,
00162   0x59, 0x56, 0x55 };
00163 /*
00164  ******************************************************************************
00165  * Globals
00166  ******************************************************************************
00167  */
00168 /* Variable below is used for non-scheduled responses. To be deprecated */
00169 uint16_t gau16CG147Responses[CG147_INPUT_BUFFER_SIZE];
00170 uint32_t gau32CG147DefaultResponses[CG147_INPUT_BUFFER_SIZE];
00172 uint8_t gu8CG147WatchDog2ResponseFromMCU;
00174 uint8_t gu8CG147WatchDog3ResponseFromMCU;
00176 uint32_t gu32CG147WatchDog2RequestToMCU;
00178 uint32_t gu32CG147WatchDog3RequestToMCU;
00180 uint16_t gu16CG147WatchDog2IsrCount;
00182 uint16_t gu16CG147WatchDog3IsrCount;
00183 /* Variables below are used to remember configuration from the user */
00185 uint8_t gu8CG147DSPIInstance;
00187 uint8_t gu8CG147DSPICS;
00189 uint8_t gau8CG147DSPIComplexInstances[2u];
00191 uint32_t gu32CG147WD2Time;
00193 uint32_t gu32CG147WD3Time;
00195 uint32_t gu32CG147WDStatus;
00196 /*
00197  ******************************************************************************
00198  * Function : vfnCG147Init()
00199  ******************************************************************************
00200  */
00201 void vfnCG147Init(const uint8_t cu8DSPIMainInstance,
00202                   const uint8_t cu8ChipSelect,
00203                   const uint8_t cu8DSPISecondaryInstance1,
00204                   const uint8_t cu8DSPISecondaryInstance2,
00205                   const uint8_t cu8NSysResPort,
00206                   const uint8_t cu8NSysResPin)
00207 {
00208   /* We're going to reset the internal logic of the CG147 now - delays are   */
00209   /* necessary to ensure correct reset behavior of the device. We justify    */
00210   /* them because this function should only be called once during start-up.  */
00211   vfnToggleOutputPin(cu8NSysResPort, cu8NSysResPin, TRUE);
00212   DELAY_MSEC(250u);
00213   vfnToggleOutputPin(cu8NSysResPort, cu8NSysResPin, CLEAR);
00214   DELAY_MSEC(38u);
00215   vfnToggleOutputPin(cu8NSysResPort, cu8NSysResPin, TRUE);
00216   DELAY_MSEC(250u);
00217   
00218   /* Start 2MHz clock through CLKOUT */
00219   vfnClockOutputEnable(ctCG147ClkOutConfig);
00220   
00221   /* Next, we init our watchdog 3 with the passed timer channel and counts */
00222   (void)u8fnCG147WatchDogStartUp();
00223   
00224   /* Remember what DSPI instance and chip select are being used */
00225   gu8CG147DSPICS = cu8ChipSelect;
00226   gu8CG147DSPIInstance = cu8DSPIMainInstance;
00227   gau8CG147DSPIComplexInstances[CLEAR] = cu8DSPISecondaryInstance1;
00228   gau8CG147DSPIComplexInstances[1u] = cu8DSPISecondaryInstance2;
00229   
00230   return;
00231 }
00232 /*
00233  ******************************************************************************
00234  * Function : u8fnCG147ReadAOut()
00235  * Functional with Direct SPI Tx in 16-bit configuration ONLY
00236  ******************************************************************************
00237  */
00238 uint8_t u8fnCG147ReadAOut(const uint8_t cu8DSPIInstance,
00239                           const uint8_t cu8ChipSelect,
00240                           const uint8_t cu8ADCInstance,
00241                           const uint8_t cu8ADCCh,
00242                           const uint8_t cu8CG147Ch,
00243                           uint16_t* pu16Result)
00244 {
00245   
00246   /* Declare local variables */
00247   uint8_t u8Status;
00248   
00249   /* Init local variables */
00250   u8Status = CLEAR;
00251   
00252   /* Ask the CG147 to output ADC data */
00253   u8Status = u8fnCG147Transcieve(SBC_AOUT_CTRL, 
00254                                  (BIT7 | cu8CG147Ch),
00255                                  cu8DSPIInstance, 
00256                                  cu8ChipSelect);
00257   
00258   if(CLEAR == u8Status)
00259   {
00260     u8Status = u8fnADCConvert(cu8ADCInstance, cu8ADCCh, pu16Result);
00261   }
00262   else
00263   {
00264     /* In this particular case, status is already set to something. Leave it */
00265   }
00266   
00267   return (u8Status);
00268 }
00269 /*
00270  ******************************************************************************
00271  * Function : u8fnCG147ReadPSI5Accel()
00272  * Functional with Direct SPI Tx in 16-bit configuration ONLY
00273  ******************************************************************************
00274  */
00275 uint8_t u8fnCG147ReadPSI5Accel(const uint8_t cu8DSPIInstance,
00276                                const uint8_t cu8ChipSelect,
00277                                uint16_t* pu16Accel)
00278 {
00279   /* Declare local variables */
00280   uint8_t u8SPIStatus;
00281   uint8_t u8Counter;
00282   
00283   /* Init local variables - keeps MISRA happy */
00284   u8SPIStatus = CLEAR;
00285   u8Counter = CLEAR;
00286   
00287   /* Loop as many times as we have sensors */
00288   u8SPIStatus = u8fnCG147BatchTranscieve((uint8_t*)cau8ReadPSISensorsCmd,
00289                                          (uint8_t*)cau8ReadPSISensorsArg,
00290                                          cu8DSPIInstance, cu8ChipSelect,
00291                                          N_ELEMENTS(cau8ReadPSISensorsArg));
00292   /* If we received data correctly, pass that to a global variable */
00293   if(CLEAR == u8SPIStatus)
00294   {
00295     *pu16Accel++ = u16fn10BitOffsetFilter(gau16CG147Responses[1u]);
00296     *pu16Accel++ = u16fn10BitOffsetFilter(gau16CG147Responses[2u]);
00297     *pu16Accel++ = u16fn10BitOffsetFilter(gau16CG147Responses[3u]);
00298     *pu16Accel++ = u16fn10BitOffsetFilter(gau16CG147Responses[4u]);
00299   }
00300   else
00301   {
00302     for(u8Counter = CLEAR; u8Counter < 4u; u8Counter++)
00303     {
00304       *pu16Accel++ = CLEAR;
00305     }
00306   } /* End else */
00307   
00308   return (u8SPIStatus);
00309 }
00310 /*
00311  ******************************************************************************
00312  * Function : u8fnCG147ReadPSI5RegSensor()
00313  * Functional with Direct SPI Tx in 16-bit configuration ONLY
00314  ******************************************************************************
00315  */
00316 uint8_t u8fnCG147ReadPSI5RegSensor(const uint8_t cu8DSPIInstance,
00317                                    const uint8_t cu8ChipSelect,
00318                                    uint16_t* pu16Accel)
00319 {
00320   /* Declare local variables */
00321   uint8_t u8SPIStatus;
00322   uint8_t u8Counter;
00323   
00324   /* Init local variables - keeps MISRA happy */
00325   u8SPIStatus = CLEAR;
00326   u8Counter = CLEAR;
00327   
00328   /* Loop as many times as we have sensors */
00329   u8SPIStatus = u8fnCG147BatchTranscieve((uint8_t*)cau8ReadPSISensorsCmd,
00330                                          (uint8_t*)cau8ReadPSISensorsArg,
00331                                          cu8DSPIInstance, cu8ChipSelect,
00332                                          N_ELEMENTS(cau8ReadPSISensorsArg));
00333   /* If we received data correctly, pass that to a global variable */
00334   if(CLEAR == u8SPIStatus)
00335   {
00336     //Debug register debug at start up
00337     *pu16Accel++ = gau16CG147Responses[1u];
00338     (void)u8fnDelay(CG147_PULSE_DELAY_20_USEC);
00339     *pu16Accel++ = gau16CG147Responses[2u];
00340     (void)u8fnDelay(CG147_PULSE_DELAY_20_USEC);
00341     *pu16Accel++ = gau16CG147Responses[3u];
00342     (void)u8fnDelay(CG147_PULSE_DELAY_20_USEC);
00343     *pu16Accel++ = gau16CG147Responses[4u];
00344     (void)u8fnDelay(CG147_PULSE_DELAY_20_USEC);
00345     
00346   }
00347   else
00348   {
00349     for(; u8Counter < N_ELEMENTS(cau8ReadPSISensorsArg); 
00350         u8Counter++)
00351     {
00352       *pu16Accel++ = CLEAR;
00353     }
00354   } /* End else */
00355   
00356   return (u8SPIStatus);
00357 }
00358 /*
00359  ******************************************************************************
00360  * u8fnCG147Transcieve
00361  *  Functional with Direct SPI Tx in 16-bit configuration ONLY
00362  ******************************************************************************
00363  */
00364 vuint8_t u8fnCG147Transcieve(uint8_t u8Cmd,
00365                              uint8_t u8Value,
00366                              uint8_t u8SPIInstance,
00367                              uint8_t u8CSToCG147)
00368 {
00369   /* Declare locals */
00370   uint16_t u16Message;
00371   
00372   /* init variables. Note that gau16CG147Responses only inits the first value*/
00373   gau16CG147Responses[CLEAR] = CLEAR;
00374   
00375   /* Construct the message only if NOfMessages can be used by au16Message */
00376   vfnCG147ComposeFrame(&u8Cmd, &u8Value, (uint16_t*)&u16Message, ((uint8_t)1u));
00377   
00378   return (u8fnDSPITranscieve(u8SPIInstance, 
00379                              u8CSToCG147,
00380                              (uint16_t*)&u16Message,
00381                              (uint16_t*)&gau16CG147Responses, 
00382                              ((uint8_t)1u)));
00383 }
00384 /*
00385  ******************************************************************************
00386  * u8fnCG147BatchTranscieve
00387  * Functional with Direct SPI Tx in 16-bit configuration ONLY
00388  ******************************************************************************
00389  */
00390 uint8_t u8fnCG147BatchTranscieve(uint8_t* pu8Cmd,
00391                                  uint8_t* pu8Value,
00392                                  uint8_t u8SPIInstance,
00393                                  uint8_t u8CSToCG147,
00394                                  uint8_t u8NOfMessages)
00395 {
00396   /* Declare locals */
00397   uint16_t au16Message[CG147_INPUT_BUFFER_SIZE];
00398   uint8_t u8Status;
00399   
00400   /* Init variables */
00401   u8Status = CLEAR;
00402   /* Construct the message only if NOfMessages can be used by au16Message */
00403   if(N_ELEMENTS(au16Message) >= u8NOfMessages)
00404   {
00405     vfnCG147ComposeFrame(pu8Cmd, pu8Value, (uint16_t*)&au16Message,
00406                          u8NOfMessages);
00407     
00408     u8Status = u8fnDSPITranscieve(u8SPIInstance, u8CSToCG147,
00409                                   (uint16_t*)&au16Message,
00410                                   (uint16_t*)&gau16CG147Responses,
00411                                   u8NOfMessages);
00412     
00413   }
00414   else
00415   {
00416     u8Status = CG147_TRANSCIEVE_ERROR;
00417   }
00418   return (u8Status);
00419 }
00420 
00421 /*
00422  ******************************************************************************
00423  * Function : u8fnCG147ScheduleAOut()
00424  * Functional with Scheduled SPI Tx in 16-bit configuration ONLY
00425  ******************************************************************************
00426  */
00427 uint8_t u8fnCG147ScheduleAOut(const uint8_t cu8DSPIInstance,
00428                               const uint8_t cu8ChipSelect,
00429                               const uint8_t cu8CG147Ch,
00430                               uint16_t* pu16Status,
00431                               uint32_t* pu32Time)
00432 {
00433   uint8_t u8Status;
00434   
00435   u8Status = u8fnCG147ScheduleTransfer(cu8DSPIInstance, cu8ChipSelect,
00436                                        SBC_AOUT_CTRL, (BIT7 | cu8CG147Ch),
00437                                        pu16Status, pu32Time);
00438   
00439   return (u8Status);
00440 }
00441 /*
00442  ******************************************************************************
00443  * Function : u8fnCG147ScheduleSPI5Accel()
00444  * Functional with Scheduled SPI Tx in 16-bit configuration ONLY
00445  ******************************************************************************
00446  */
00447 uint8_t u8fnCG147SchedulePSI5Accel(const uint8_t cu8DSPIInstance,
00448                                    const uint8_t cu8ChipSelect,
00449                                    uint16_t* pu16Accel,
00450                                    uint32_t* pu32Time)
00451 {
00452   
00453   uint8_t u8SPIStatus;
00454   
00455   /* Schedule a batch transfer of the defined values in our table */
00456   u8SPIStatus
00457       = u8fnCG147ScheduleBatchTransfer(cu8DSPIInstance, cu8ChipSelect,
00458                                        (uint8_t*)cau8ReadPSISensorsCmd,
00459                                        (uint8_t*)cau8ReadPSISensorsArg,
00460                                        pu16Accel,
00461                                        N_ELEMENTS(cau8ReadPSISensorsArg),
00462                                        pu32Time);
00463   return (u8SPIStatus);
00464 }
00465 /*
00466  ******************************************************************************
00467  * u8fnCG147ScheduleTransfer
00468  * Functional with Scheduled SPI Tx in 16-bit configuration ONLY
00469  ******************************************************************************
00470  */
00471 uint8_t u8fnCG147ScheduleTransfer(uint8_t u8SPIInstance,
00472                                   uint8_t u8CSToCG147,
00473                                   uint8_t u8Cmd,
00474                                   uint8_t u8Value,
00475                                   uint16_t* pu16Response,
00476                                   uint32_t* pu32RequestTime)
00477 {
00478   uint8_t u8Status;
00479   uint16_t u16Message;
00480   
00481   u8Status = CLEAR;
00482   
00483   /* Construct the message only if NOfMessages can be used by au16Message */
00484   vfnCG147ComposeFrame(&u8Cmd, &u8Value, (uint16_t*)&u16Message, ((uint8_t)1u));
00485   
00486   /* Schedule the transfer */
00487   u8Status = u8fnSchedDSPIMailTransfer(u8SPIInstance, u8CSToCG147, CLEAR,
00488                                        CLEAR, (uint16_t*)&u16Message,
00489                                        pu16Response, ((uint8_t)1u));
00490   SCHED_WHEN_WAS_THE_LAST_TX_DONE(*pu32RequestTime);
00491   
00492   return (u8Status);
00493 }
00494 /*
00495  ******************************************************************************
00496  * u8fnCG147ScheduleBatchTransfer
00497  * Functional with Scheduled SPI Tx in 16-bit configuration ONLY
00498  ******************************************************************************
00499  */
00500 uint8_t u8fnCG147ScheduleBatchTransfer(uint8_t u8SPIInstance,
00501                                        uint8_t u8CSToCG147,
00502                                        uint8_t* pu8Cmd,
00503                                        uint8_t* pu8Value,
00504                                        uint16_t* pu16Response,
00505                                        uint8_t u8Size,
00506                                        uint32_t* pu32RequestTime)
00507 {
00508   uint8_t u8Status;
00509   uint16_t au16Message[CG147_INPUT_BUFFER_SIZE];
00510   
00511   u8Status = CLEAR;
00512   
00513   /* Construct the message only if NOfMessages can be used by au16Message */
00514   vfnCG147ComposeFrame(pu8Cmd, pu8Value, (uint16_t*)&au16Message, u8Size);
00515   
00516   /* Schedule the transfer */
00517   u8Status = u8fnSchedDSPIMailTransfer(u8SPIInstance, u8CSToCG147, CLEAR,
00518                                        CLEAR, (uint16_t*)&au16Message,
00519                                        pu16Response, u8Size);
00520   SCHED_WHEN_WAS_THE_LAST_TX_DONE(*pu32RequestTime);
00521   
00522   return (u8Status);
00523 }
00524 /*
00525  ******************************************************************************
00526  * Function : u8fnCG147ScheduleSafeAOut()
00527  * Functional with Scheduled SPI Tx in 17-bit configuration ONLY
00528  ******************************************************************************
00529  */
00530 uint8_t u8fnCG147ScheduleSafeAOut(const uint8_t cu8DSPIInstance1,
00531                                   const uint8_t cu8DSPIInstance2,
00532                                   const uint8_t cu8ChipSelect,
00533                                   const uint8_t cu8CG147Ch,
00534                                   uint32_t* pu32Status,
00535                                   uint32_t* pu32Time)
00536 {
00537   /* We will schedule a transfer with the AOUT_CTRL message set. */
00538   return (u8fnCG147ScheduleSafeTransfer(cu8DSPIInstance1, 
00539                                         cu8DSPIInstance2,
00540                                         cu8ChipSelect, 
00541                                         SBC_AOUT_CTRL, 
00542                                         (BIT7 | cu8CG147Ch),
00543                                         (uint16_t*)pu32Status, pu32Time));
00544   
00545 }
00546 
00547 /*
00548  ******************************************************************************
00549  * Function : u8fnCG147ScheduleSPI5Accel()
00550  * Functional with Scheduled SPI Tx in 17-bit configuration ONLY
00551  ******************************************************************************
00552  */
00553 uint8_t u8fnCG147ScheduleSafePSI5Accel(const uint8_t cu8DSPIInstance1,
00554                                        const uint8_t cu8DSPIInstance2,
00555                                        const uint8_t cu8ChipSelect,
00556                                        const uint16_t cu16ActiveChannels,
00557                                        uint32_t* pu32RawAccel,
00558                                        uint32_t* pu32Time)
00559 {
00560   
00561   uint8_t u8SPIStatus;
00562   uint8_t u8Counter1;
00563   uint8_t u8Counter2;
00564   uint16_t u16Mask;
00565   uint8_t au8Args[N_ELEMENTS(cau8ReadPSISensorsArg)];
00566   
00567   /* Based on the variable cu16ActiveChannels, we must determine which */
00568   /* are the active channels in the system. We will reconstruct the    */
00569   /* consant, generic table based out of cau8ReadPSISensorsCmd and Arg */
00570   /* based on this.                                                    */
00571   /* Init counter to 0 */
00572   u8Counter1 = CLEAR;
00573   u8Counter2 = CLEAR;
00574   for(u16Mask = CG147_SAT_MASK_MIN; u16Mask < CG147_SAT_MASK_MAX; 
00575       u16Mask <<= ((uint16_t)1u))
00576   {
00577     if(u16Mask & cu16ActiveChannels)
00578     {
00579       au8Args[u8Counter2] = cau8ReadPSISensorsArg[u8Counter1];
00580       u8Counter2++;
00581     }
00582     else
00583     {
00584       /* Skip this one */
00585     }
00586     u8Counter1++;
00587   }
00588 
00589   /* Finish by writing the last argument to something logical, for example 0 */
00590   au8Args[u8Counter2++] = CLEAR;
00591   
00592   /* Schedule a batch transfer of the defined values in our table */
00593   u8SPIStatus
00594       = u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1, cu8DSPIInstance2,
00595                                            cu8ChipSelect,
00596                                            (uint8_t*)cau8ReadPSISensorsCmd,
00597                                            (uint8_t*)au8Args,
00598                                            (uint16_t*)pu32RawAccel, u8Counter2,
00599                                            pu32Time);
00600   return (u8SPIStatus);
00601 }
00602 /*
00603  ******************************************************************************
00604  * Function : u8fnCG147ScheduleSafeSquibFireStart()
00605  * Functional with Scheduled SPI Tx in 17-bit configuration ONLY
00606  ******************************************************************************
00607  */
00608 uint8_t u8fnCG147ScheduleSafeSquibFireStart(const uint8_t cu8DSPIInstance1,
00609                                             const uint8_t cu8DSPIInstance2,
00610                                             const uint8_t cu8ChipSelect,
00611                                             uint16_t u16ChannelMask,
00612                                             uint32_t* pu32Time)
00613 {
00614   uint8_t u8Status;
00615   uint8_t au8LocalArgs[N_ELEMENTS(cau8CG147FireSquibsDfltArgs)];
00616   
00617   /* This function shall be called once the decision to fire has been    */
00618   /* made and all proper checks have taken place. It offers no decision  */
00619   /* making.                                                             */
00620 
00621   /* 6. set the external pin EN_FL to high */
00622   vfnToggleOutputPin(PIN_EN_FL, TRUE);
00623   
00624   /* 7. unlock low side and high side power stage by SPI command FLM_LOCK */
00625   u8Status
00626       = u8fnCG147ScheduleSafeTransfer(cu8DSPIInstance1, cu8DSPIInstance2,
00627                                       cu8ChipSelect, SBC_FLM_LOCK,
00628                                       CG147_UNLOCK_HS_LS,
00629                                       (uint16_t*)gau32CG147DefaultResponses,
00630                                       pu32Time);
00631   /* 8. turn on low side power stage by SPI command LS_ON */
00632 
00633   /* The mask argument is used to determine which channels will be fired */
00634   /* using a pre-calculated table to off-load the processor.             */
00635   au8LocalArgs[CLEAR] = cau8SquibOnPrecalc[u16ChannelMask & 0x000Fu];
00636   au8LocalArgs[1u] = cau8SquibOnPrecalc[(u16ChannelMask >> 4u) & 0x000Fu];
00637   au8LocalArgs[2u] = cau8SquibOnPrecalc[(u16ChannelMask >> 8u) & 0x000Fu];
00638   
00639   u8Status
00640       |= u8fnCG147ScheduleSafeBatchTransfer(
00641                                             cu8DSPIInstance1,
00642                                             cu8DSPIInstance2,
00643                                             cu8ChipSelect,
00644                                             (uint8_t*)&cau8CG147FireLSSquibsCmds,
00645                                             (uint8_t*)&au8LocalArgs,
00646                                             (uint16_t*)gau32CG147DefaultResponses,
00647                                             N_ELEMENTS(cau8CG147FireLSSquibsCmds),
00648                                             pu32Time);
00649   
00650   /* 9. wait for 20 us */
00651   /* We will perform this wait by scheduling a fake SPI transfer. Note */
00652   /* that Chip Select is clear */
00653   u8Status
00654       |= u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1,
00655                                             cu8DSPIInstance2,
00656                                             CLEAR,
00657                                             (uint8_t*)&cau8CG147FireHSSquibsCmds,
00658                                             (uint8_t*)&cau8CG147FireSquibsDfltArgs,
00659                                             (uint16_t*)gau32CG147DefaultResponses,
00660                                             CG147_SPI_FAKE_TIME_20US, pu32Time);
00661   /* 10. turn on highside power stage by SPI command HS_ON */
00662   u8Status
00663       |= u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1,
00664                                             cu8DSPIInstance2,
00665                                             cu8ChipSelect,
00666                                             (uint8_t*)&cau8CG147FireHSSquibsCmds,
00667                                             (uint8_t*)&au8LocalArgs,
00668                                             (uint16_t*)gau32CG147DefaultResponses,
00669                                             N_ELEMENTS(cau8CG147FireLSSquibsCmds),
00670                                             pu32Time);
00671   return (u8Status);
00672 }
00673 /*
00674  ******************************************************************************
00675  * u8fnCG147ScheduleSafeSquibFireStop
00676  * Functional with Scheduled SPI Tx in 17-bit configuration ONLY
00677  ******************************************************************************
00678  */
00679 uint8_t u8fnCG147ScheduleSafeSquibFireStop(const uint8_t cu8DSPIInstance1,
00680                                            const uint8_t cu8DSPIInstance2,
00681                                            const uint8_t cu8ChipSelect,
00682                                            uint32_t* pu32Time)
00683 {
00684   uint8_t u8Status;
00685   
00686   /* 1. turn off high side power stage by SPI command HS_ON */
00687   u8Status
00688       = u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1,
00689                                            cu8DSPIInstance2,
00690                                            cu8ChipSelect,
00691                                            (uint8_t*)&cau8CG147FireHSSquibsCmds,
00692                                            (uint8_t*)&cau8CG147FireSquibsDfltArgs,
00693                                            (uint16_t*)&gau32CG147DefaultResponses,
00694                                            N_ELEMENTS(cau8CG147FireHSSquibsCmds),
00695                                            pu32Time);
00696   /* 2. wait for at least 50 us */
00697   /* We will wait a little longer by making sure the data above has been sent. */
00698   while(1u > u32fnSchedIsTxDone(*pu32Time))
00699   {
00700     /* Wait here */
00701   };
00702   
00703   /* 3. turn off low side power stage by SPI command LS_ON */
00704   u8Status
00705       |= u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1,
00706                                             cu8DSPIInstance2,
00707                                             cu8ChipSelect,
00708                                             (uint8_t*)&cau8CG147FireLSSquibsCmds,
00709                                             (uint8_t*)&cau8CG147FireSquibsDfltArgs,
00710                                             (uint16_t*)&gau32CG147DefaultResponses,
00711                                             N_ELEMENTS(cau8CG147FireLSSquibsCmds),
00712                                             pu32Time);
00713   
00714   /* Bring the enable firing loop pin low again */
00715   vfnToggleOutputPin(PIN_EN_FL, CLEAR);
00716   
00717   return (u8Status);
00718 }
00719 /*
00720  ******************************************************************************
00721  * u8fnCG147ScheduleSafeSquibFireStop
00722  * Functional with Scheduled SPI Tx in 17-bit configuration ONLY
00723  ******************************************************************************
00724  */
00725 uint8_t u8fnCG147ScheduleSafeTest(const uint8_t cu8DSPIInstance1,
00726                                   const uint8_t cu8DSPIInstance2,
00727                                   const uint8_t cu8ChipSelect,
00728                                   uint8_t u8TestCase,
00729                                   uint32_t* pu32Result,
00730                                   uint16_t* pu16ADCResponses,
00731                                   uint32_t* pu32Time)
00732 {
00733   uint8_t u8Status;
00734   uint8_t au8ArgsForFirstPart[2u];
00735   
00736   /* No matter what the test is, we need to disable the boost convert */
00737   /* transistor (T2) first. This is scheduled and hard-coded below.   */
00738   /* Refer to CG147's spec for details. */
00739   au8ArgsForFirstPart[0u] = ((uint8_t)0x01u);
00740   
00741   /* Next we must schedule the actual test. */
00742   au8ArgsForFirstPart[1u] = u8TestCase;
00743   
00744   /* Store the current Voltage level in Aout */
00745   vfnTransferADCResults(CLEAR, pu16ADCResponses, CG147_N_ADC_DATA);
00746   
00747   /* Schedule this transfer */
00748   u8Status
00749       = u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1,
00750                                            cu8DSPIInstance2,
00751                                            cu8ChipSelect,
00752                                            (uint8_t*)&cau8CG147TestCmds[CLEAR],
00753                                            (uint8_t*)&au8ArgsForFirstPart[CLEAR],
00754                                            (uint16_t*)&gau32CG147DefaultResponses,
00755                                            CG147_TEST_CMD_SIZE_FIRST_PART,
00756                                            pu32Time);
00757   
00758   /* Depending on the test mode is the amount of time we must wait.      */
00759   if(CG147_TEST_IS_VER_ESR == u8TestCase)
00760   {
00761     /* Specially critical is when VER ESR test is enabled since we cannot  */
00762     /* stay on for more than 100 usec. Since scheduler is set for 100 usec */
00763     /* SPI transfers, we will wait for the message to be sent plus an      */
00764     /* extra cycle to send the next command.                               */
00765     while(1u > u32fnSchedIsTxDone(*pu32Time))
00766     {
00767       /* Wait here */
00768     }
00769     /* Now we continue... with less than 100 usec on the clock. */
00770   }
00771   else
00772   {
00773     /* If this is not the case, we will be waiting no more than 200 msec,   */
00774     /* which is a long time here. We will use a delay fn instead, and allow */
00775     /* the scheduler to take care of watchdog elements.                     */
00776     DELAY_MSEC(CG147_LONG_TEST_WAIT_MS);
00777     /* Store the current Voltage level in Aout  */
00778     /* Enough time has elapsed since the previous request to be able to      */
00779     /* call again without overwriting */
00780     vfnTransferADCResults(CLEAR, pu16ADCResponses, CG147_N_ADC_DATA);
00781     DELAY_MSEC(2u);
00782   }
00783 
00784   /* Now for the grand finale, we must restore original behavior, read back */
00785   /* results, and move on.                                                  */
00786   u8Status
00787       = u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1,
00788                                            cu8DSPIInstance2,
00789                                            cu8ChipSelect,
00790                                            (uint8_t*)&cau8CG147TestCmds[CG147_TEST_CMD_SIZE_FIRST_PART],
00791                                            (uint8_t*)&cau8CG147TestArgs[CG147_TEST_CMD_SIZE_FIRST_PART],
00792                                            (uint16_t*)pu32Result,
00793                                            CG147_TEST_CMD_SIZE_SECOND_PART,
00794                                            pu32Time);
00795   return (u8Status);
00796 }
00797 /*
00798  ******************************************************************************
00799  * u8fnCG147ScheduleSafeTransfer
00800  * Functional with Scheduled SPI Tx in 17-bit configuration ONLY
00801  ******************************************************************************
00802  */
00803 uint8_t u8fnCG147ScheduleSafeTransfer(const uint8_t cu8SPIInstance1,
00804                                       const uint8_t cu8SPIInstance2,
00805                                       const uint8_t cu8CSToCG147,
00806                                       uint8_t u8Cmd,
00807                                       uint8_t u8Value,
00808                                       uint16_t* pu16Response,
00809                                       uint32_t* pu32RequestTime)
00810 {
00811   uint8_t u8Status;
00812   uint16_t u16SafeValue;
00813   uint16_t u16SafeCmd;
00814   uint8_t u8ParityValue;
00815   
00816   u8Status = CLEAR;
00817   u16SafeCmd = (uint16_t)u8Cmd;
00818   
00819   /* We will construct a safe command by adding a parity bit at the end and */
00820   /* in so doing, creating a 17-bit word.                                   */
00821 
00822   /* We know that the command part is always Odd */
00823   /* Calculate the value for the argument only */
00824   u8ParityValue = u8fnCheckOddParity(u8Value, CLEAR);
00825   
00826   /* Store it in a 16-bit variable through an XNOR with a parity bit that */
00827   /* is always clear. We know this because the command part is always odd. */
00828   u16SafeValue = (uint16_t)(u8Value << 1u) | (uint16_t)(!u8ParityValue);
00829   
00830   /* Schedule the transfer */
00831   u8Status = u8fnSchedCompositeDSPIMailTransfer(cu8SPIInstance1,
00832                                                 cu8SPIInstance2, cu8CSToCG147,
00833                                                 (uint16_t*)&u16SafeCmd,
00834                                                 (uint16_t*)&u16SafeValue,
00835                                                 (const uint16_t*)pu16Response,
00836                                                 (uint16_t)1u);
00837   SCHED_WHEN_WAS_THE_LAST_TX_DONE(*pu32RequestTime);
00838   
00839   return (u8Status);
00840 }
00841 /*
00842  ******************************************************************************
00843  * u8fnCG147ScheduleSafeBatchTransfer
00844  * Functional with Scheduled SPI Tx in 17-bit configuration ONLY
00845  ******************************************************************************
00846  */
00847 uint8_t u8fnCG147ScheduleSafeBatchTransfer(const uint8_t cu8SPIInstance1,
00848                                            const uint8_t cu8SPIInstance2,
00849                                            const uint8_t cu8CSToCG147,
00850                                            uint8_t* pu8Cmd,
00851                                            uint8_t* pu8Value,
00852                                            uint16_t* pu16Response,
00853                                            uint8_t u8Size,
00854                                            uint32_t* pu32RequestTime)
00855 {
00856   uint8_t u8Status;
00857   uint16_t au16SafeCommand[CG147_INPUT_BUFFER_SIZE];
00858   uint16_t au16SafeValue[CG147_INPUT_BUFFER_SIZE];
00859   uint8_t u8ParityValue;
00860   uint8_t u8Counter;
00861   
00862   u8Status = CLEAR;
00863   
00864   /* We will construct a safe command by adding a parity bit at the end and */
00865   /* in so doing, creating a 17-bit word.                                   */
00866   for(u8Counter = CLEAR; u8Counter < u8Size; u8Counter++)
00867   {
00868     /* We know that the command part is always Odd */
00869     /* Calculate the value for the argument only */
00870     u8ParityValue = u8fnCheckOddParity(*(pu8Value + u8Counter), CLEAR);
00871     /* Store it in a 16-bit variable through an XNOR with a parity bit that */
00872     /* is already set. We know this because the command part is always odd. */
00873     au16SafeValue[u8Counter] = (uint16_t)(*(pu8Value + u8Counter) << 1u) |
00874     (uint16_t)(!u8ParityValue);
00875     au16SafeCommand[u8Counter] = (uint16_t)(*(pu8Cmd + u8Counter));
00876   }
00877 
00878   /* Schedule the transfer */
00879   u8Status = u8fnSchedCompositeDSPIMailTransfer(cu8SPIInstance1,
00880                                                 cu8SPIInstance2, cu8CSToCG147,
00881                                                 (uint16_t*)au16SafeCommand,
00882                                                 (uint16_t*)&au16SafeValue,
00883                                                 pu16Response, u8Size);
00884   SCHED_WHEN_WAS_THE_LAST_TX_DONE(*pu32RequestTime);
00885   
00886   return (u8Status);
00887 }
00888 /*
00889  ******************************************************************************
00890  * Function : vfnCG147SyncPulse()
00891  ******************************************************************************
00892  */
00893 void vfnCG147SyncPulse(const uint8_t cu8NSyncPort, const uint8_t cu8NSyncPin)
00894 {
00895   /* N_SYNC_ON */
00896   vfnToggleOutputPin(cu8NSyncPort, cu8NSyncPin, TRUE);
00897   (void)u8fnDelay((uint16_t)CG147_PULSE_DELAY_40_USEC);
00898   
00899   /* N_SYNC_OFF */
00900   vfnToggleOutputPin(cu8NSyncPort, cu8NSyncPin, CLEAR);
00901   ;
00902   
00903   return;
00904 }
00905 /*
00906  ******************************************************************************
00907  * Function : WatchDogStartUp()
00908  ******************************************************************************
00909  */
00910 uint8_t u8fnCG147WatchDogStartUp(void)
00911 {
00912   
00913   /* Init all Watchdog responses */
00914   gu8CG147WatchDog2ResponseFromMCU = cau8CG147WDResponsesFromMCU[CLEAR];
00915   gu8CG147WatchDog3ResponseFromMCU = cau8CG147WDResponsesFromMCU[CLEAR];
00916   gu32CG147WatchDog2RequestToMCU = cau8CG147WDRequestsToMCU[CLEAR];
00917   gu32CG147WatchDog3RequestToMCU = cau8CG147WDRequestsToMCU[CLEAR];
00918   
00919   return (CLEAR);
00920 }
00921 /*
00922  ******************************************************************************
00923  * u8fnCG147WatchDogNextWord
00924  ******************************************************************************
00925  */
00926 uint8_t u8fnCG147WatchDogNextWord(const uint8_t u8WordFromSBC)
00927 {
00928   uint8_t u8ResponseFromMCU;
00929   uint8_t u8LoopCounter;
00930   
00931   /* Init locals */
00932   u8LoopCounter = CLEAR;
00933   u8ResponseFromMCU = CLEAR;
00934   
00935   /* Loop through the defined responses to find ours */
00936   do
00937   {
00938     if(cau8CG147WDRequestsToMCU[u8LoopCounter] == u8WordFromSBC)
00939     {
00940       if((N_ELEMENTS(cau8CG147WDRequestsToMCU) - 1u) > u8LoopCounter)
00941       {
00942         u8ResponseFromMCU = cau8CG147WDResponsesFromMCU[u8LoopCounter + 1u];
00943       }
00944       else
00945       {
00946         u8ResponseFromMCU = cau8CG147WDResponsesFromMCU[CLEAR];
00947       }
00948     }
00949     else
00950     {
00951       /* Nothing */
00952     }
00953   }while((N_ELEMENTS(cau8CG147WDRequestsToMCU) > u8LoopCounter++)
00954         && (u8ResponseFromMCU == CLEAR));
00955 
00956   /* In case of no error */
00957   if(u8ResponseFromMCU != CLEAR)
00958   {
00959     /* Nothing */
00960   }
00961   else
00962   {
00963     /* Error case. Restart the message sequence */
00964     u8ResponseFromMCU = SBC_WD_RESPONSE_8;
00965   }
00966 
00967   return(u8ResponseFromMCU);
00968 }
00969 
00970 /*
00971  ******************************************************************************
00972  * u8fnCG147ComposeFrame
00973  ******************************************************************************
00974  */
00975 void vfnCG147ComposeFrame(uint8_t* pu8Cmd,
00976                           uint8_t* pu8Value,
00977                           uint16_t* pu16ComposedMessage,
00978                           uint8_t u8Size)
00979 {
00980   /* All SBC commands use a parity bit that is only calculated with the */
00981   /* command section of the message. Therefore, the parity can be       */
00982   /* pre-calculated to unload processor tasks. All defines in the       */
00983   /* corresponding .h file have been through this process. This routine */
00984   /* will no longer calculate it, and the user must make sure that      */
00985   /* the commands are part of the defines, or that parity has been      */
00986   /* calculated prior to calling it.                                    */
00987 
00988   /* Do as long as we have bytes */
00989   for(; u8Size > CLEAR; u8Size--)
00990   {
00991     /* Construct the message according to the CG147 format: */
00992     /* BIT15 - BIT9 = Instruction                           */
00993     /* BIT8 = Odd parity                                    */
00994     /* BIT7 - BIT0 = Input data                             */
00995     *pu16ComposedMessage = (uint16_t)(*pu8Cmd << BITS_IN_BYTE) | 
00996                            (uint16_t)*pu8Value;
00997 
00998     /* Increment pointers to the next position */
00999     pu16ComposedMessage++;
01000     pu8Cmd++;
01001     pu8Value++;
01002   }
01003   
01004   return;
01005 }
01006 /*
01007  ******************************************************************************
01008  * u16fnCG147ExtractScheduledPSI5Accel
01009  ******************************************************************************
01010  */
01011 uint16_t u16fnCG147ExtractScheduledPSI5Accel(const uint32_t* pu32RawResponse,
01012                                              uint16_t* pu16Accel,
01013                                              const uint16_t cu16ChannelsMask)
01014 {
01015   /* Declare locals */
01016   uint8_t u8Status;
01017   uint16_t u16Status;
01018   uint8_t u8Counter1;
01019   uint8_t u8Counter2;
01020   uint16_t u16LocalMask;
01021   uint8_t u8DummyRead;
01022   
01023   /* Init locals */
01024   u8Status = CLEAR;
01025   u16Status = CLEAR;
01026   u8DummyRead = CLEAR;
01027   u8Counter1 = CLEAR;
01028   u8Counter2 = CLEAR;
01029   
01030   /* First element is only to select the first device, but can be ignored */
01031   /* as long as the status is clear */
01032   u8Status = u8fnCG147ExtractResponse(pu32RawResponse, (uint8_t*)&u8DummyRead);
01033   
01034   /* We will select the next elements based on the passed value u16ChannelsMask */
01035   for(u16LocalMask = CG147_SAT_MASK_MIN; u16LocalMask < CG147_SAT_MASK_MAX; 
01036       u16LocalMask <<= (uint16_t)1u)
01037   {
01038     if(u16LocalMask & cu16ChannelsMask)
01039     {
01040       u8Counter1++;
01041       u8Status = u8fnCG147ExtractPSIAccel((uint32_t*)(pu32RawResponse + u8Counter1),
01042           (uint16_t*)(pu16Accel + u8Counter2));
01043       if(u8Status != CLEAR)
01044       {
01045         u16Status |= u16LocalMask;
01046       }
01047       else
01048       {
01049         /* Nothing */
01050       }
01051     }
01052     else
01053     { 
01054 
01055     }
01056     u8Counter2++;
01057   }
01058   
01059   return (u16Status);
01060 }
01061 /*
01062  ******************************************************************************
01063  * u8fnCG147ExtractPSIAccel
01064  ******************************************************************************
01065  */
01066 uint8_t u8fnCG147ExtractPSIAccel(const uint32_t* pu32RawResponse,
01067                                  uint16_t* pu16Accel)
01068 {
01069   uint8_t u8Status;
01070     
01071   u8Status = CLEAR;
01072   
01073   /* First verify that the transfered data's parity is correct */
01074   if(CLEAR == u8fnCG147VerifyParityFromSafeResult(*pu32RawResponse))
01075   {
01076     /* If we're good, we want to report*/
01077     u8Status = (uint8_t)(*pu32RawResponse >> BITS_IN_16)
01078                & CG147_ACCEL_STATUS_BYTE_MASK;
01079     *pu16Accel = (uint16_t)((*pu32RawResponse >> 1u) & UCHAR_MAX)
01080                  | (uint16_t)((*pu32RawResponse >> BITS_IN_BYTE)
01081                  & (CG147_ACCEL_READING_MASK << BITS_IN_BYTE));
01082   }
01083   else
01084   {
01085     u8Status = CG147_RESPONSE_PARITY_FAILURE;
01086   }
01087   
01088   return (u8Status);
01089 }
01090 /*
01091  ******************************************************************************
01092  * u8fnCG147ExtractResponse
01093  ******************************************************************************
01094  */
01095 uint8_t u8fnCG147ExtractResponse(const uint32_t* pu32RawResponse,
01096                                  uint8_t* pu8Response)
01097 {
01098   uint8_t u8Status;
01099   
01100   u8Status = CLEAR;
01101   
01102   /* First verify that the transfered data's parity is correct */
01103   if(CLEAR == u8fnCG147VerifyParityFromSafeResult(*pu32RawResponse))
01104   {
01105     /* If we're good, we will return the status coming from the device */
01106     u8Status = (uint8_t)(*pu32RawResponse >> BITS_IN_16) & 
01107                CG147_RESPONSE_STATUS_BYTE_MASK;
01108     /* And our response will be that coming from the response minus the */
01109     /* parity bit, which is at the end */
01110     *pu8Response = (uint8_t)(*pu32RawResponse >> 1u);
01111   }
01112   else
01113   {
01114     u8Status = CG147_RESPONSE_PARITY_FAILURE;
01115   }
01116   
01117   return (u8Status);
01118 }
01119 /*
01120  ******************************************************************************
01121  * u8fnCG147VerifyParityFromSafeResult
01122  ******************************************************************************
01123  */
01124 static uint8_t u8fnCG147VerifyParityFromSafeResult(uint32_t u32ComplexResponse)
01125 {
01126   /* Response is stored as a 32-bit word where the 8MSB of the transfer */
01127   /* are stored in the second byte, and the 9 LSB are stored in the     */
01128   /* next half. We will need to calculate parity as the combination of  */
01129   /* an 8-bit word + the parity of a 16-bit word.                       */
01130   uint8_t u8ParityHigh;
01131   uint8_t u8ParityLow;
01132   
01133   u8ParityHigh
01134       = u8fnCheckOddParity((uint8_t)(u32ComplexResponse >> 16u), CLEAR);
01135   u8ParityLow = (uint8_t)u16fnCheckOddParity((uint16_t)u32ComplexResponse,
01136                                              CLEAR);
01137   
01138   return (!(u8ParityHigh ^ u8ParityLow));
01139 }
01140 /*
01141  ******************************************************************************
01142  * u16fn10BitOffsetFilter
01143  ******************************************************************************
01144  */
01145 uint16_t u16fn10BitOffsetFilter(uint16_t u16RawValue)
01146 {
01147   /* Local variables */
01148   uint16_t u16CorrectedValue;
01149   
01150   /* Init locals to make MISRA happy */
01151   u16CorrectedValue = CLEAR;
01152   
01153   /* Let's check the status of the sign bit and act accordingly */
01154   if(SIGN_10_BITS == (SIGN_10_BITS & u16RawValue))
01155   {
01156     u16CorrectedValue = (u16RawValue & MAX_VALUE_10_BITS) - SIGN_10_BITS;
01157   }
01158   else
01159   {
01160     u16CorrectedValue = (u16RawValue & MAX_VALUE_10_BITS) + SIGN_10_BITS;
01161   }
01162   
01163   return (u16CorrectedValue);
01164 }
01165 
01166 /*
01167  ******************************************************************************
01168  * vfnCG147WD2Isr
01169  * Functional with Scheduled SPI Tx in 17-bit configuration ONLY
01170  ******************************************************************************
01171  */
01172 void vfnCG147WD2Isr(void)
01173 {
01174   
01175   /* Calculate the next word */
01176   /* Increment WD3 counter */
01177   if(++gu16CG147WatchDog2IsrCount >= CG147_WD2_COUNT_FOR_ISR)
01178   {
01179     gu16CG147WatchDog2IsrCount = CLEAR;
01180     gu8CG147WatchDog2ResponseFromMCU
01181         = u8fnCG147WatchDogNextWord((uint8_t)((gu32CG147WatchDog2RequestToMCU
01182                                               & 0x1FE) >> 1u));
01183     
01184     if(CLEAR != u8fnCG147ScheduleSafeTransfer(gau8CG147DSPIComplexInstances[0u],
01185                                   gau8CG147DSPIComplexInstances[1u],
01186                                   gu8CG147DSPICS, SBC_WD2_TRIGGER,
01187                                   (uint8_t)gu8CG147WatchDog2ResponseFromMCU,
01188                                   (uint16_t*)(&gu32CG147WatchDog2RequestToMCU),
01189                                   (uint32_t*)&gu32CG147WD2Time))
01190     {
01191       /* Reschedule. */
01192       gu8RescheduleSource |= RESCH_SRC_2;
01193       vfnPITStart(gu8ReSchPITCh, TRUE);
01194     }
01195     else
01196     {
01197       /* Nothing */
01198     }
01199     
01200     /* Increment WD3 counter */
01201     if(++gu16CG147WatchDog3IsrCount >= CG147_WD3_COUNT_FOR_ISR)
01202     {
01203       gu16CG147WatchDog3IsrCount = CLEAR;
01204       /* Calculate the next word */
01205       gu8CG147WatchDog3ResponseFromMCU
01206           = u8fnCG147WatchDogNextWord((uint8_t)((gu32CG147WatchDog3RequestToMCU
01207                                                 & 0x1FE) >> 1u));
01208       
01209       if(CLEAR != u8fnCG147ScheduleSafeTransfer(gau8CG147DSPIComplexInstances[0u],
01210                                                 gau8CG147DSPIComplexInstances[1u],
01211                                                 gu8CG147DSPICS, SBC_WD3_TRIGGER,
01212                                                 (uint8_t)gu8CG147WatchDog3ResponseFromMCU,
01213                                                 (uint16_t*)(&gu32CG147WatchDog3RequestToMCU),
01214                                                 (uint32_t*)&gu32CG147WD3Time))
01215       {
01216         /* Reschedule. */
01217         gu8RescheduleSource |= RESCH_SRC_3;
01218         vfnPITStart(gu8ReSchPITCh, TRUE);
01219       }
01220     }
01221     else
01222     {
01223       /* Nothing */
01224     }
01225     u8fnCG147ScheduleSafeTransfer(gau8CG147DSPIComplexInstances[0u],
01226                                   gau8CG147DSPIComplexInstances[1u],
01227                                   gu8CG147DSPICS, SBC_READ_WD_STATUS,
01228                                   CLEAR,
01229                                   (uint16_t*)(&gu32CG147WDStatus),
01230                                   (uint32_t*)&gu32CG147WD2Time);
01231 //    u8fnCG147ScheduleSafeTransfer(gau8CG147DSPIComplexInstances[0u],
01232 //                                      gau8CG147DSPIComplexInstances[1u],
01233 //                                      gu8CG147DSPICS, SBC_READ_WD_FC,
01234 //                                      CLEAR,
01235 //                                      (uint16_t*)(&gu32CG147DebugDummy),
01236 //                                                        (uint32_t*)&gu32CG147DebugDummy);
01237   }
01238   else
01239   {
01240     /* Nothing */
01241   }
01242   
01243   /* Clear the flag */
01244   CLEAR_ISR_FLAG(CG147_WD2_ISR_CH);
01245   
01246   return;
01247 }
01248 
01249 void vfnReScheduleWD(void)
01250 {
01251   /* Clear flag that brought us here */
01252   CLEAR_ISR_FLAG(SCHED_RESCHED_2);
01253   if(CLEAR == u8fnCG147ScheduleSafeTransfer(gau8CG147DSPIComplexInstances[0u],
01254                                     gau8CG147DSPIComplexInstances[1u],
01255                                     gu8CG147DSPICS, SBC_WD2_TRIGGER,
01256                                     (uint8_t)gu8CG147WatchDog2ResponseFromMCU,
01257                                     (uint16_t*)(&gu32CG147WatchDog2RequestToMCU),
01258                                     (uint32_t*)&gu32CG147WD2Time))
01259   {
01260     gu8RescheduleSource &= ~RESCH_SRC_2;
01261   }
01262   else
01263   {
01264     /* Keep waiting until appropriate */
01265   }
01266 }
01267 void vfnReScheduleWD3(void)
01268 {
01269   /* Clear flag that brought us here */
01270   CLEAR_ISR_FLAG(SCHED_RESCHED_3);
01271   if(CLEAR == u8fnCG147ScheduleSafeTransfer(gau8CG147DSPIComplexInstances[0u],
01272                                     gau8CG147DSPIComplexInstances[1u],
01273                                     gu8CG147DSPICS, SBC_WD3_TRIGGER,
01274                                     (uint8_t)gu8CG147WatchDog3ResponseFromMCU,
01275                                     (uint16_t*)(&gu32CG147WatchDog3RequestToMCU),
01276                                     (uint32_t*)&gu32CG147WD3Time))
01277   {
01278     gu8RescheduleSource &= ~RESCH_SRC_3;
01279   }
01280   else
01281   {
01282     /* Keep waiting until appropriate */
01283   }
01284 }
01285 /*
01286  ******************************************************************************
01287  *
01288  *  End of file.
01289  *
01290  ******************************************************************************
01291  */